#-*- encoding:utf-8 -*-
#用户版图形化界面

#GUI图形库
import tkinter as tk
from tkinter import messagebox

#自定义文件
import RSA_op
import SHA256_op
import File
import Certificate_CA

#绑定用户
def setuser():
    user = user_text.get().lstrip()
    if len(user) == 0:
            messagebox.showwarning('警告','用户名不能为空, 请重新输入')
    else:
        if user!='CA':
            try:
                f = open("CA_private.key", 'r')
                f.close
                f = open("CA_public.key", 'r')
                f.close
            except:
                messagebox.showwarning('警告','CA的公钥或私钥文件不存在，请检查后重新启动本程序')
                root.destroy()

        btn_setuser['state'] = 'disable'
        btn_resetuser['state'] = 'normal'
        user_input['state'] = 'readonly'
        btn_create_file['state'] = 'normal'
        btn_create_key['state'] = 'normal'
        btn_create_cer['state'] = 'normal'
        btn_verify['state'] = 'normal'
        btn_cancel['state'] = 'normal'
        start_input['state'] = 'normal'
        use_input['state'] = 'normal'
        messagebox.showinfo('提示', '用户'+user+'已绑定')
            

#重新绑定用户
def resetuser():
    user_text.set('')
    btn_setuser['state'] = 'normal'
    btn_resetuser['state'] = 'disable'
    user_input['state'] = 'normal'
    btn_create_file['state'] = 'disable'
    btn_create_key['state'] = 'disable'
    btn_create_cer['state'] = 'disable'
    btn_verify['state'] = 'disable'
    btn_cancel['state'] = 'disable'
    start_input['state'] = 'disable'
    use_input['state'] = 'disable'
    messagebox.showinfo('提示','用户绑定已解除')

#生成密钥文件
def create_key():
    rst = File.create_key_file(user_text.get().lstrip())
    if rst == 1:
            messagebox.showinfo('提示',user_text.get().lstrip()+'密钥文件已生成')

#生成证书申请文件
def create_file():
    rst = Certificate_CA.apply_certificate(user_text.get().lstrip())
    if rst == -1:
            messagebox.showwarning("警告", "公钥文件不存在，请将公钥文件放在当前目录下")
    else:
            messagebox.showinfo("提示", "证书申请文件已成功生成")

#生成证书
def create_cer():
    start = start_input.get().lstrip()
    use = use_input.get().lstrip()
    try:
        start = int(start)
        use = int(use)
    except:
        messagebox.showwarning("警告", "生效时间和有效期只能是数字")
    rst = Certificate_CA.finish_certificate(user_text.get().lstrip(), start, use)
    if rst == -1:
            messagebox.showwarning("警告", "申请文件不存在，请将申请文件放在当前目录下")
    if rst == -2:
            messagebox.showwarning("警告", "CA配置文件不存在，请将CA配置文件放在当前目录下")
    else:
            messagebox.showinfo("提示", "证书文件已成功生成，请手动上传至FTP")

#说明
def create_cer_read():
    messagebox.showinfo('生成证书说明','\t生成证书注意事项\
        \n1. 生成证书时需要如下文件:\
        \n\t 申请文件(用户名_apply.csr)\
        \n\t CA的配置文件(CA.ini)\
        \n\t CA的公钥与私钥(CA_public.key, CA_private.key)\
        \n2. 生效时间为证书的起始有效时间, 以天为单位, 默认为0, 0表示现在, 负数表示提前若干天生效, 正数表示延迟若干天生效\
        \n3. 有效期为证书的总有效时间, 以生效时间开始计算, 以天为单位, 默认为30, 不可为负数\
        \n4. 请勿修改程序生成证书的文件名，防止出现不可预估的后果')

#验证证书
def verify():
        rst = Certificate_CA.verify_certificate(user_text.get().lstrip())
        if rst == -1:
                messagebox.showwarning('警告','证书文件不存在')
        elif rst == -2:
                messagebox.showwarning('警告','证书文件已被吊销')
        elif rst == -3:
                messagebox.showwarning('警告','证书文件尚未生效')
        elif rst == -4:
                messagebox.showwarning('警告','证书文件已过期')
        elif rst == 0:
                messagebox.showwarning('警告','证书验证不通过，内容可能已被篡改')
        else:
                messagebox.showinfo("提示","该证书通过了验证")

#吊销证书
def cancel_cer():
    var_box = tk.messagebox.askyesno(title='提示',message='即将吊销'+user_text.get().lstrip()+"的证书，是否继续？")
    if var_box:
        rst = Certificate_CA.cancel_certificate(user_text.get().lstrip())
        if rst == -1:
            messagebox.showwarning('警告','证书文件不存在')
        else:
            messagebox.showinfo('提示','证书文件已被吊销，请尽快更新FTP中的证书吊销列表')

#生成CA配置文件
def create_ini():
    ca_name = ca_text.get().lstrip()
    with open('CA.ini',"w") as f:
        f.write("CA name:"+ca_name) 
    messagebox.showinfo('提示','CA配置文件已生成')

#说明
def readme():
    messagebox.showinfo('使用说明','\t欢迎使用模拟CA系统的CA端\
        \n注意事项\
        \n1. 使用时需要设置需要操作的用户名，设定后可以取消绑定\
        \n2. 第一次使用时需要绑定用户名CA，然后生成CA的公钥和私钥即可正常使用\
        \n3. 不设置用户名，您将无法正常使用本程序\
        \n4. 密钥文件会生成在本地，与当前程序在同一文件夹下，用户名即为已绑定的用户名，请妥善保管您的密钥，一旦丢失将无法找回\
        \n5. 生成的证书申请文件会保留在当前文件夹下\
        \n6. 生成证书需要在证书申请文件中补全信息，原文件会保留，请手动将证书申请文件下载回本地，并将生成的证书传回FTP\
        \n7. 验证证书需要将对方的证书放于当前目录下，且仅能验证绑定的用户名的证书，如需验证他人的请重新绑定\
        \n8. 吊销证书需要将最新的吊销文件及时放入FTP服务器中，方便验证时使用\
        \n9. 请勿修改程序生成文件的文件名，防止出现不可预估的后果')

#退出按钮
def cancel():
        root.destroy()

if __name__ == '__main__':
        root = tk.Tk()
        root.title('模拟CA系统-CA版')
        root.geometry("450x200+200+50")  #窗口的大小

        # 第一行
        row1 = tk.Frame()
        row1.pack(fill="x", ipadx=1, pady=5)
        user_text = tk.StringVar()
        tk.Label(row1, text='要操作的用户:', width=20).pack(side=tk.LEFT)
        user_input = tk.Entry(row1, textvariable=user_text, width=25)
        user_input.pack(side=tk.LEFT)
        btn_resetuser= tk.Button(row1, text="取消绑定", command=resetuser, state=tk.DISABLED)
        btn_resetuser.pack(side=tk.RIGHT, padx=5)
        btn_setuser= tk.Button(row1, text="绑定", command=setuser)
        btn_setuser.pack(side=tk.RIGHT, padx=5)
        
        # 第二行
        row2 = tk.Frame()
        row2.pack(fill="x", ipadx=1, pady=5)
        btn_create_key = tk.Button(row2, text="生成密钥", command=create_key, state=tk.DISABLED)
        btn_create_key.pack(side=tk.LEFT,  padx=20)
        btn_create_file = tk.Button(row2, text="生成证书申请文件", command=create_file, state=tk.DISABLED)
        btn_create_file.pack(side=tk.LEFT,  padx=20)
        btn_verify= tk.Button(row2, text="验证证书", command=verify, state=tk.DISABLED)
        btn_verify.pack(side=tk.LEFT, padx=20)
        btn_cancel = tk.Button(row2, text="吊销证书", command=cancel_cer, state=tk.DISABLED)
        btn_cancel.pack(side=tk.RIGHT,  padx=20)
        
        # 第三行
        row3 = tk.Frame()
        row3.pack(fill="x", ipadx=1, pady=5)
        start_text = tk.StringVar()
        start_text.set('0')
        tk.Label(row3, text='生效时间:', width=15).pack(side=tk.LEFT)
        start_input = tk.Entry(row3, textvariable=start_text, width=5, state=tk.DISABLED)
        start_input.pack(side=tk.LEFT)
        use_text = tk.StringVar()
        use_text.set('30')
        tk.Label(row3, text='有效期:', width=10).pack(side=tk.LEFT)
        use_input = tk.Entry(row3, textvariable=use_text, width=5, state=tk.DISABLED)
        use_input.pack(side=tk.LEFT)
        btn_create_cer = tk.Button(row3, text="生成证书", command=create_cer, state=tk.DISABLED)
        btn_create_cer.pack(side=tk.LEFT,  padx=10)
        tk.Button(row3, text="生成说明", command=create_cer_read).pack(side=tk.LEFT)

        # 第四行
        row4 = tk.Frame()
        row4.pack(fill="x", ipadx=1, pady=5)
        ca_text = tk.StringVar()
        tk.Label(row4, text='CA名称:', width=15).pack(side=tk.LEFT)
        ca_input = tk.Entry(row4, textvariable=ca_text, width=25)
        ca_input.pack(side=tk.LEFT)
        btn_ini= tk.Button(row4, text="生成配置文件", command=create_ini)
        btn_ini.pack(side=tk.LEFT, padx=35)

        # 第五行
        row5 = tk.Frame()
        row5.pack(fill="y", ipadx=10, padx=10, side=tk.BOTTOM)
        tk.Button(row5, text="退出", command=cancel).pack(side=tk.RIGHT)
        tk.Button(row5, text="说明", command=readme).pack(side=tk.RIGHT,  padx=10)

        root.mainloop()